<?php

class Workset_File_Handler_Image_GD extends Workset_File_Handler_Abstract
                                    implements Workset_File_Handler_Image_Interface
{

    protected $_init = null;

    protected $_resource = null;

    protected $_quality = 100;

    /**
     * Возвращает ширину картинки
     *
     * @return int
     */
    public function getWidth() {
        $res = $this->_getResource();
        return imagesx($res);
    }

    /**
     * Возвращает высоту картинки
     *
     * @return int
     */
    public function getHeight() {
        $res = $this->_getResource();
        return imagesy($res);
    }

    /**
     * Устанавливает качество для сохраняемой картинки
     *
     * @throws Zend_Exception
     * @param  int $q
     * @return Workset_File_Handler_Image_GD
     */
    public function setQuality($q) {
        if ($q > 0) {
            $this->_quality = (int)$q;
        } else {
            throw new Zend_Exception('Quality must be greater then 0');
        }
        return $this;
    }

    /**
     * Возвращает установленное качество для сохраняемой картинки
     *
     * @return int
     */
    public function getQuality() {
        return $this->_quality;
    }

    /**
     * Пропорционально масштабирует картинку по указанной стороне (ширина или высота)
     *
     * @throws Zend_Exception
     * @param  $side - width|height
     * @param  $size
     * @return Workset_File_Handler_Image_GD
     */
    public function resizeBySide($side, $size) {
        $img = $this->_getResource();

        $w = $this->getWidth();
        $h = $this->getHeight();

        $newW = ($side == "height") ? floor(($w * $size) / $h) : $size;
        $newH = ($side == "width") ? floor(($h * $size) / $w) : $size;

        $x = 0;
        $y = 0;

        $newImg = imagecreatetruecolor($newW, $newH);
        $result = imagecopyresampled($newImg, $img, 0, 0, $x, $y, $newW, $newH, $w, $h);

        if ($result) {
            $this->_setResource($newImg);
        } else {
            throw new Zend_Exception('Cannot resize image');
        }

        return $this;
    }

    /**
     * Сохраняет картинку на диске
     *
     * @return bool
     */
    public function save() {
        $this->_flush();
        return true;
    }

	/**
	 * Возможно ли работать с изображением данного типа
	 *
	 * @return bool
	 */
    public function isAvailable() {
        if (null !== $this->_init) {
            return $this->_init;
        }

        if (defined('GD_VERSION') && (int)GD_VERSION >= 2) {
            $type = exif_imagetype($this->_file->getRealPath());

            if (imagetypes() & $type) {
                return $this->_init = true;
            }
        }

        return $this->_init = false;
    }

    /**
     * Возвращает расширение для изображения
     *
     * @return string
     */
    public function getExtension() {
        return $this->isAvailable() ? image_type_to_extension( exif_imagetype( $this->_file->getRealPath() ), false) : null;
    }

    protected function _getResource() {
        if (null !== $this->_resource) {
            return $this->_resource;
        }

        if (!$this->isAvailable()) {
            throw new Zend_Exception("GD2 extension not support or unknown image type");
        }

        $source = file_get_contents( $this->_file->getRealPath() );

        if ($res = @imagecreatefromstring($source)) {
            $this->_resource = $res;
			return $this->_resource;
		} else {
            throw new Zend_Exception('Cannot create GD image resource');
        }
    }

    protected function _setResource($resource) {
        $this->_resource = $resource;
    }

    protected function _flush() {
        $f = $this->_getOutputFunction();
        if ( $f( $this->_getResource(), $this->_file->getRealPath(), $this->_quality )) {
            $this->_clearResource();
        } else {
            throw new Zend_Exception('Cannot save image on disk');
        }
    }

    protected function _clearResource() {
        $this->_resource = null;

        //обновляем информацию о файле
        $class = get_class($this->_file);
        $this->_file = new $class( $this->_file->getRealPath() );
    }

    protected function _getOutputFunction() {
        $ext = $this->getExtension();
        $f = null;

        if (is_string($ext)) {
            $f = 'image'.$ext;
        }

        if (null !== $f && function_exists($f)) {
            return $f;
        } else {
            throw new Zend_Exception('Unknown function name "' . $f . '"');
        }
    }

}
